package com.spring.mvc.loader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

public class JarClassLoader extends AbstractClassLoader {
	
	private List<String> classRepositoy;
	private List<JarResources> jarsRepositoy;
	private List<String> pathRepositoy;
	
	public JarClassLoader() {
		super(JarClassLoader.class.getClassLoader());
		this.classRepositoy=new ArrayList<String>();
		this.jarsRepositoy=new ArrayList<JarResources>();
		this.pathRepositoy=new ArrayList<String>();
		init();
	}
	
	public void addClassPath(String classPath){
		StringTokenizer tokenizer=new StringTokenizer(classPath,File.separator);
		while(tokenizer.hasMoreTokens()){
			String ss = tokenizer.nextToken();
			if(!this.classRepositoy.contains(ss)){
				this.classRepositoy.add(ss);
			}
		}
	}
	
	private void init(){
		String ss;
		ss=System.getProperty("SERV_HOME")+File.separator+"service";
		this.classRepositoy.add(ss);
		this.classRepositoy.add(ss+File.separator+"classes");
		addJarPath(ss);
		
		ss=System.getProperty("SERV_HOME")+File.separator+"plugin";
		addJarPath(ss);
		
		loadJarResouseFormPath();
	}
	
	public void addJarPath(String pathName){
		if(!this.pathRepositoy.contains(pathName)){
			this.pathRepositoy.add(pathName);
		}
	}
	
	private synchronized void loadJarResouseFormPath(){
		Iterator<String> paths;
		try {
			paths=this.pathRepositoy.iterator();
			while(paths.hasNext()){
				String pathName=paths.next();
				loadDir(pathName);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void loadDir(String pathName){
		File file;
		try {
			file=new File(pathName);
			if(file.exists()){
				if(file.isDirectory()){
					File[] files=file.listFiles();
					for (File f:files) {
						if(f.isDirectory()){
							loadDir(f.getCanonicalPath()); 
						}else if(f.getName().toLowerCase().endsWith(".jar"))
							this.jarsRepositoy.add(new JarResources(f.getCanonicalPath()));
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	protected byte[] loadClassBytes(String className) {
		ByteArrayOutputStream baos=null;
		ObjectOutputStream oos=null;
		try {
			Class<?> classObj=loadClass(className);
			Object obj=classObj.newInstance();
			baos=new ByteArrayOutputStream();
			oos=new ObjectOutputStream(baos);
			oos.writeObject(obj);
			byte[] b=baos.toByteArray();
			return b;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			try {
				if(oos!=null){
					oos.close();
					oos=null;
				}
				if(baos!=null){
					baos.close();
					baos=null;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	
	public static void main(String[] args) {
		System.setProperty("SERV_HOME","D:\\test");
		new JarClassLoader();
	}
}
